package manage

import (
	"github.com/gin-gonic/gin"
	"gpt-api/framework/auther"
	"gpt-api/framework/cache"
	"gpt-api/framework/codes"
	"gpt-api/framework/db"
	"gpt-api/framework/ginplus"
	"gpt-api/framework/log"
	"gpt-api/pkg/model"
	"gpt-api/pkg/util"
	"strconv"
	"time"
)

type Handler struct {
	db     *db.DB
	cache  *cache.RedisClient
	auther auther.Auther
}

func New(db *db.DB, cache *cache.RedisClient, auther auther.Auther) *Handler {

	return &Handler{db: db, cache: cache, auther: auther}
}

func (h *Handler) UsersLogin(c *gin.Context) error {
	var (
		req struct {
			Username string `json:"username" binding:"required"`
			Password string `json:"password" binding:"required"`
		}
		user model.AdminUser
	)
	if err := c.Bind(&req); err != nil {
		return ginplus.ReplyBadRequest(c, err)
	}
	has, err := db.GetOne(h.db.Where("username = ?", req.Username), &user)
	if err != nil {
		return ginplus.ReplyInternalError(c, err)
	}
	if !has {
		return ginplus.ReplyError(c, codes.UnknownAccount, nil)
	}
	if user.Password != util.Md5(req.Password) {
		return ginplus.ReplyError(c, codes.InvalidPassword, nil) // password error
	}

	tkinfo, err := h.auther.GenerateToken(&auther.UserInfo{UserId: user.ID})
	if err != nil {
		log.Error("generate token error", log.Errval(err))
		return ginplus.ReplyInternalError(c, nil)
	}

	return ginplus.ReplyJSON(c, gin.H{"token": tkinfo.GetAccessToken()})
}

type orders struct {
	Date        time.Time `json:"date"`                   //日期
	Channel     int       `json:"channel,omitempty"`      //渠道
	OrderNumber string    `json:"order_number,omitempty"` //订单号
	Amount      float64   `json:"amount,omitempty"`       //支付金额
}
type Re struct {
	Date        uint64  `json:"date"`                   //日期
	Channel     int     `json:"channel,omitempty"`      //渠道
	OrderNumber string  `json:"order_number,omitempty"` //订单号
	Amount      float64 `json:"amount,omitempty"`       //支付金额
}

func (h *Handler) OrderList(c *gin.Context) error {
	var (
		req struct {
			Page        int    `form:"page"`
			Size        int    `form:"size"`
			Channel     int    `form:"channel"`
			StartTime   int64  `form:"start_time"`
			EndTime     int64  `form:"end_time"`
			OrderNumber string `form:"order_number"` //	订单号

		}
		resp []orders
		RESP []Re
	)
	if err := c.Bind(&req); err != nil {
		return ginplus.ReplyBadRequest(c, err)
	}
	CreateBegin := util.TimestampDayBegin(req.StartTime, time.UTC, 8)
	CreateEnd := util.TimestampDayEnd(req.EndTime, time.UTC, 8)
	//	查询订单表
	tx := h.db.Model(new(model.Document)).
		Select("document.id,document.created_at as date,document.status,document.type as channel,document.amount,document.doc_number as order_number").
		Where("document.status=?", 2)
	if req.Channel > 0 {
		tx = tx.Where("document.type = ?", req.Channel)
	}
	if req.OrderNumber != "" {
		tx = tx.Where("document.doc_number = ?", req.OrderNumber)
	}
	if req.StartTime != 0 {
		tx = tx.Where("created_at >= ? and created_at <= ?", CreateBegin, CreateEnd)
	}
	total, err := db.FindPage(tx.Order("id desc"), req.Page, req.Size, &resp)
	if err != nil {
		return ginplus.ReplyInternalError(c, err)
	}
	for _, v := range resp {
		RESP = append(RESP, Re{
			Date:        uint64(v.Date.Unix()) - 28800,
			Channel:     v.Channel,
			OrderNumber: v.OrderNumber,
			Amount:      v.Amount,
		})
	}

	return ginplus.ReplyJSON(c, gin.H{"total": total, "orders": RESP})
}

type loglist struct {
	Date    time.Time //日期
	Channel int       //渠道
	Cate    string    //分类
	Action  string    //行为
}
type respLog struct {
	Date    uint64 `json:"date"` //日期
	Channel int    //渠道
	Cate    string //分类
	Action  string //行为
}

func (h *Handler) GetLogList(c *gin.Context) error {
	var (
		req struct {
			Page      int    `form:"page"`
			Size      int    `form:"size"`
			Channel   int    `form:"channel"`
			StartTime int64  `form:"start_time"`
			EndTime   int64  `form:"end_time"`
			Cate      string `form:"cate"`
			Action    string `form:"action"`
		}
		resp []loglist
		Resp []respLog
	)
	if err := c.Bind(&req); err != nil {
		return ginplus.ReplyBadRequest(c, err)
	}
	//写一条SQL语句，查询时间转为时间戳，然后查询
	CreateBegin := util.TimestampDayBegin(req.StartTime, time.UTC, 8)
	CreateEnd := util.TimestampDayEnd(req.EndTime, time.UTC, 8)

	tx := h.db.Model(new(model.AdLog)).Select("ad_logs.id,ad_logs.created_at as date," +
		"ad_logs.platform_type as channel,ad_logs.cate,ad_logs.action")
	if req.Channel > 0 {
		tx = tx.Where("ad_logs.platform_type = ?", req.Channel)
	}
	if req.StartTime != 0 {
		tx = tx.Where("ad_logs.created_at >= ? and ad_logs.created_at <= ?", CreateBegin, CreateEnd)
	}
	if req.Cate != "" {
		tx = tx.Where("ad_logs.cate = ?", req.Cate)
	}
	total, err := db.FindPage(tx.Order("id desc"), req.Page, req.Size, &resp)
	if err != nil {
		return ginplus.ReplyInternalError(c, err)
	}
	for _, v := range resp {
		Resp = append(Resp, respLog{
			Date:    uint64(v.Date.Unix()) - 28800,
			Channel: v.Channel,
			Cate:    v.Cate,
			Action:  v.Action,
		})
	}

	return ginplus.ReplyJSON(c, gin.H{"total": total, "loglist": Resp})
}

type res struct {
	Channel          string `json:"channel,omitempty"`  //渠道
	Date             string `json:"date"`               //日期
	TotalHomeVisit   int64  `json:"total_home_visit"`   //介绍页浏览数
	TotalHomeClick   int64  `json:"total_home_click"`   //开始测算
	TotalResultVisit int64  `json:"total_result_visit"` //下单页浏览数
	TotalResultClick int64  `json:"total_result_click"` //下单页下单
	TotalOrder       int    `json:"total_order"`        //成功付费下单数
	DayAmounts       int    `json:"day_amounts"`        //当日支付金额
}
type Res struct {
	List []res `json:"list,omitempty"` //渠道
}

func (h *Handler) GetOverview(c *gin.Context) error {
	var (
		req struct {
			Date    []string `json:"date"`
			Channel int      `json:"channel"`
		}
		resp Res
	)
	if err := c.BindJSON(&req); err != nil {
		return ginplus.ReplyBadRequest(c, err)
	}
	switch req.Channel {
	case 1:
		for _, v := range req.Date {
			resp.List = append(resp.List, res{
				Channel:          "OPPO",
				Date:             v,
				TotalHomeVisit:   h.secletadlods(1, "home", v, "visit") + h.secletadlods(11, "home", v, "visit") + h.secletadlods(4, "home", v, "visit"),
				TotalHomeClick:   h.secletadlods(1, "home", v, "click") + h.secletadlods(11, "home", v, "click") + h.secletadlods(4, "home", v, "click"),
				TotalResultVisit: h.secletadlods(1, "result", v, "visit") + h.secletadlods(11, "result", v, "visit") + h.secletadlods(4, "result", v, "visit"),
				TotalResultClick: h.secletadlods(1, "result", v, "click") + h.secletadlods(11, "result", v, "click") + h.secletadlods(4, "result", v, "click"),
				TotalOrder:       h.totalOrder(1, v).Total + h.totalOrder(11, v).Total + h.totalOrder(4, v).Total,
				DayAmounts:       h.totalOrder(1, v).Amounts + h.totalOrder(11, v).Amounts + +h.totalOrder(4, v).Amounts,
			})
		}

	case 2:
		for _, v := range req.Date {
			resp.List = append(resp.List, res{
				Channel:          "ViVo",
				Date:             v,
				TotalHomeVisit:   h.secletadlods(2, "home", v, "visit") + h.secletadlods(22, "home", v, "visit"),
				TotalHomeClick:   h.secletadlods(2, "home", v, "click") + h.secletadlods(22, "home", v, "click"),
				TotalResultVisit: h.secletadlods(2, "result", v, "visit") + h.secletadlods(22, "result", v, "visit"),
				TotalResultClick: h.secletadlods(2, "result", v, "click") + h.secletadlods(22, "result", v, "click"),
				TotalOrder:       h.totalOrder(2, v).Total + h.totalOrder(22, v).Total,
				DayAmounts:       h.totalOrder(2, v).Amounts + h.totalOrder(22, v).Amounts,
			})
		}
	case 3:
		for _, v := range req.Date {
			resp.List = append(resp.List, res{
				Channel:          "公众号",
				Date:             v,
				TotalHomeVisit:   h.secletadlods(3, "home", v, "visit"),
				TotalHomeClick:   h.secletadlods(3, "home", v, "click"),
				TotalResultVisit: h.secletadlods(3, "result", v, "visit"),
				TotalResultClick: h.secletadlods(3, "result", v, "click"),
				TotalOrder:       h.totalOrder(3, v).Total,
				DayAmounts:       h.totalOrder(3, v).Amounts,
			})
		}
	case 6:
		for _, v := range req.Date {
			resp.List = append(resp.List, res{
				Channel:          "推啊",
				Date:             v,
				TotalHomeVisit:   h.secletadlods(6, "home", v, "visit"),
				TotalHomeClick:   h.secletadlods(6, "home", v, "click"),
				TotalResultVisit: h.secletadlods(6, "result", v, "visit"),
				TotalResultClick: h.secletadlods(6, "result", v, "click"),
				TotalOrder:       h.totalOrder(6, v).Total,
				DayAmounts:       h.totalOrder(6, v).Amounts,
			})
		}
	default:
		for _, v := range req.Date {
			resp.List = append(resp.List, res{
				Channel:          strconv.Itoa(req.Channel),
				Date:             v,
				TotalHomeVisit:   h.secletadlods(req.Channel, "home", v, "visit"),
				TotalHomeClick:   h.secletadlods(req.Channel, "home", v, "click"),
				TotalResultVisit: h.secletadlods(req.Channel, "result", v, "visit"),
				TotalResultClick: h.secletadlods(req.Channel, "result", v, "click"),
				TotalOrder:       h.totalOrder(req.Channel, v).Total,
				DayAmounts:       h.totalOrder(req.Channel, v).Amounts,
			})
		}
	}

	return ginplus.ReplyJSON(c, gin.H{"log": Res{
		List: resp.List,
	}})
}

type Totals struct {
	Total   int `json:"total"`
	Amounts int `json:"amounts"`
}

func (h *Handler) totalOrder(channel int, date string) Totals {
	var count int
	var amounts float64
	total := 0
	sr := util.StrToTimestamp(date)
	CreateBegin := util.TimestampDayBegin(sr, time.UTC, 8)
	CreateEnd := util.TimestampDayEnd(sr, time.UTC, 8)
	err := h.db.Model(new(model.Document)).
		Select("count(*)").
		Where("type = ?", channel).Where("status=?", 2).
		Where("created_at >= ? ", CreateBegin).
		Where("created_at <= ? ", CreateEnd).Scan(&count).Error
	if err != nil {
		log.Error("获取订单失败", log.Var("err", err))
		return Totals{
			Total:   0,
			Amounts: 0,
		}
	}
	total = count
	err = h.db.Model(new(model.Document)).
		Select("COALESCE(SUM(document.amount),0)").
		Where("type = ?", channel).
		Where("status=?", 2).
		Where("created_at >= ? ", CreateBegin).
		Where("created_at <= ? ", CreateEnd).Scan(&amounts).Error
	if err != nil {
		log.Error("获取订单失败", log.Var("err", err))
		return Totals{
			Total:   0,
			Amounts: 0,
		}
	}
	if total == 0 {
		return Totals{Total: 0, Amounts: 0}
	}
	return Totals{
		Total:   total,
		Amounts: int(amounts),
	}
}
func (h *Handler) secletadlods(channel int, cate, date, action string) int64 {
	var re int64
	sr := util.StrToTimestamp(date)
	CreateBegin := util.TimestampDayBegin(sr, time.UTC, 8)
	CreateEnd := util.TimestampDayEnd(sr, time.UTC, 8)
	var total int64
	err := h.db.Model(new(model.AdLog)).
		Select("count(*)").
		Where("platform_type = ?", channel).
		Where("cate = ?", cate).
		Where("action = ?", action).
		Where("created_at >= ? ", CreateBegin).
		Where("created_at <= ? ", CreateEnd).Scan(&re).Error
	if err != nil {
		log.Error("获取日志失败", log.Var("err", err))
		return 0
	}
	total = re

	return total
}
